package com.hnust.service.impl;

import com.hnust.dao.*;
import com.hnust.domain.Student;
import com.hnust.domain.Teacher;
import com.hnust.domain.record.AlternativeAnswerRecord;
import com.hnust.domain.record.NewQuestionRecord;
import com.hnust.service.UpLoadService;
import com.hnust.util.IDUtil;
import com.hnust.util.PictureIO;
import com.spire.doc.Document;
import com.spire.doc.Section;
import com.spire.doc.collections.ParagraphCollection;
import com.spire.doc.documents.Paragraph;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;

@Service
public class UpLoadServiceImpl implements UpLoadService {

	@Autowired
	GradRequirementsDAO gradRequirementsDAO;
	@Autowired
	MajorDao majorDao;
	@Autowired
	CourseDao courseDao;
	@Autowired
	CourseTargetDao courseTargetDao;
	@Autowired
	StudentDao studentDao;
	@Autowired
	ClassDao classDao;
	@Autowired
	CollegeDao collegeDao;
	@Autowired
	QuestionTypeDao questionTypeDao;
	@Autowired
	CapterDao capterDao;
	@Autowired
	QuestionDao questionDao;


	@Override
	@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
	public String readChapter(MultipartFile file,String courseId) throws Exception {
			String filePath = "";
			try{
				filePath = upload(file);
			} catch (Exception e) {
				throw new Exception( "文件上传失败："+e.getMessage());
			}
			Document document = new Document();
			document.loadFromFile(filePath);
			int j=0;
			try {
				//根据专业代码获取专业ID
				Section section = document.getSections().get(0);
				//对于每一段存储数据
				for (j = 0; j < section.getParagraphs().getCount(); j++) {
					Paragraph paragraph = section.getParagraphs().get(j);
					String[] text = paragraph.getText().trim().split(" ");
					String name = text[1];
					text = text[0].split("\\.");
					if(text.length<2) {
						continue;
					}
					courseDao.insertChapter(IDUtil.getPrimaryKey(),name,Integer.parseInt(text[0]),Integer.parseInt(text[1]),Integer.parseInt(text[2]),Integer.parseInt(text[3]),courseId);
				}
			}catch (Exception e){
				e.printStackTrace();
				if("class org.springframework.dao.DuplicateKeyException".equals(e.getClass().toString())) {
					throw new Exception( "数据已存在-"+"问题可能出现在第"+(j+1)+"组数据");
				} else {
					throw new Exception( "文件读取失败：格式错误-"+"问题可能出现在第"+(j+1)+"组数据");
				}
			}
			//删除文件
			try{
				File willDeleteFile = new File(filePath);
				if(!willDeleteFile.delete()){
					throw new Exception( "文件删除失败！");
				}
			}catch(Exception e){
				throw new Exception("文件删除失败："+e.getMessage());
			}
			return "成功";
		}


		/*
	 * @Author Tonited
	 * @Description //TODO 上传文件，判断文件是否符合规范，最终返回上传文件的路径
	 * @Date 16:31 2020/10/29
	 * @Param [file]
	 * @return java.lang.String
	 **/
	@Override
	public String upload(MultipartFile file) throws Exception {
			// 获取文件名
			String fileName = file.getOriginalFilename();
			// 获取文件的后缀名
			String suffixName = fileName.substring(fileName.lastIndexOf("."));
			if(!".docx".equals(suffixName) && !".doc".equals(suffixName)) {
				if(!".xls".equals(suffixName) && !".xlsx".equals(suffixName)) {
					throw new Exception("文件不符合规范");
				}
			}
			// 文件上传后的路径
			String filePath = System.getProperty("user.dir")+"/assets/upload/";
			File dest = new File(filePath + fileName);
			// 检测是否存在目录
			if (!dest.getParentFile().exists()) {
				dest.getParentFile().mkdirs();
			}
			file.transferTo(dest);
			return filePath+fileName;
		}
		
		
		
	/*
	 * @Author Tonited
	 * @Description //TODO 读取上传的专业毕业要求分解指标点文件并存入数据库，返回报错信息
	 * @Date 16:38 2020/10/29
	 * @Param [file]
	 * @return java.lang.String
	 **/
	@Override
	@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
	public String readGradFile(MultipartFile file,String collageId) throws Exception {
		String filePath = "";
		try{
			filePath = upload(file);
		} catch (Exception e) {
			throw new Exception( "文件上传失败："+e.getMessage());
		}
		Document document = new Document();
		document.loadFromFile(filePath);
		try {
			//根据专业代码获取专业ID
			Section section = document.getSections().get(0);
			String majNum = section.getParagraphs().get(1).getText().split(" ")[1];
			System.out.println(majNum+" "+collageId);
			String majorID = majorDao.getMajIdByMajNum(majNum,collageId);
			//对于每一段存储数据
			for (int j = 3; j < section.getParagraphs().getCount(); j++) {
				Paragraph paragraph = section.getParagraphs().get(j);
				String[] text = paragraph.getText().trim().split(" ");
				if(text.length<2) {
					continue;
				}
				gradRequirementsDAO.addGradRequirement(IDUtil.getPrimaryKey(),majorID,text[0].trim(),text[1].trim());
			}
		}catch (Exception e){
			if("class org.springframework.dao.DuplicateKeyException".equals(e.getClass().toString())) {
				throw new Exception( "数据已存在");
			} else {
				throw new Exception( "文件读取失败：格式错误");
			}
		}
		//删除文件
		try{
			File willDeleteFile = new File(filePath);
			if(!willDeleteFile.delete()){
				throw new Exception( "文件删除失败！");
			}
		}catch(Exception e){
			throw new Exception("文件删除失败："+e.getMessage());
		}
		return "成功";
	}


	/*
	 * @Author Tonited
	 * @Description //TODO 读取上传课程目标文件，将其与专业毕业要求分解指标点对应，并存入数据库，返回报错信息
	 * @Date 15:30 2020/10/30
	 * @Param [file, collageId]
	 * @return java.lang.String
	 **/
	@Override
	@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
	public String readCoutarFile(MultipartFile file,String collageId) throws Exception {
		String filePath = "";
		try{
			filePath = upload(file);
		} catch (Exception e) {
			throw new Exception( "文件上传失败："+e.getMessage());
		}
		Document document = new Document();
		document.loadFromFile(filePath);
		int nowJ = 0;
		try {
			//根据课程代码获取专业ID
			Section section = document.getSections().get(0);
			String majNum = section.getParagraphs().get(1).getText();
			String majorID = majorDao.getMajIdByMajNum(majNum,collageId);
			String couNum = section.getParagraphs().get(3).getText();
			String couID = courseDao.getCouIdByCouNum(couNum);
			//对于每一段存储数据
			for (int j =5; j < section.getParagraphs().getCount(); j++) {
				nowJ = j;
				Paragraph paragraph = section.getParagraphs().get(j);
				String[] text = paragraph.getText().trim().split("\\s+");
				//长度小于2说明数据有问题
				if(text.length<2||text.length>3) {
					throw new Exception("数据格式错误");
				}
				if(text.length==2){
					courseTargetDao.insertCourseTarget(IDUtil.getPrimaryKey(), couID, null, text[1], majorID, text[0]);
				}
				if(text.length==3) {
					String gradId = gradRequirementsDAO.getIdByNumAndMajID(text[1], majorID);
					if (gradId == null) {
						throw new Exception("无指定毕业要求指标点");
					}
					courseTargetDao.insertCourseTarget(IDUtil.getPrimaryKey(), couID, gradId, text[2], majorID, text[0]);
				}

			}
		}catch (Exception e){
			if("class org.springframework.dao.DuplicateKeyException".equals(e.getClass().toString())) {
				throw new Exception( "数据已存在");
			} else {
				throw new Exception("文件读取失败：格式错误-"+e.getMessage()+" 问题可能发生在第"+(nowJ-4)+"组数据");
			}
		}
		File willDeleteFile = new File(filePath);
		if(!willDeleteFile.delete()){
			throw new Exception("文件删除失败");
		}
		return "成功";
	}

	/*
	 * @Author Tonited
	 * @Description //TODO 读取批量上传学生文件并返回学生列表及提示，如果发生错误则返回null和报错信息，初始账号和密码都是学号
	 * @Date 8:46 2020/10/30
	 * @Param [file,collageId]
	 * @return java.util.Map<java.lang.String,java.lang.Object>
	 	msg:报错信息String，list:学生列表List<Student>
	 **/
	@Override
	@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
	public Map<String, Object> readStudsent(MultipartFile file, String collageId) throws Exception {
		String filePath = "";
		ArrayList list = new ArrayList();

		try {
			filePath = this.upload(file);
		} catch (Exception var22) {
			throw new Exception("文件上传失败：" + var22.getMessage());
		}

		Workbook wb = null;
		FormulaEvaluator formulaEvaluator = null;
		File excelFile = new File(filePath);
		InputStream is = new FileInputStream(filePath);
		if (excelFile.getName().endsWith("xlsx")) {
			wb = new XSSFWorkbook(is);
			new XSSFFormulaEvaluator((XSSFWorkbook)wb);
		} else {
			wb = new HSSFWorkbook(is);
			new HSSFFormulaEvaluator((HSSFWorkbook)wb);
		}

		Sheet sheet = ((Workbook)wb).getSheetAt(0);
		int nowJ = 1;

		try {
			while(true) {
				Row studentRow = sheet.getRow(nowJ);
				if (studentRow == null) {
					break;
				}

				String studentNum = studentRow.getCell(0).getStringCellValue();
				if (studentNum.isEmpty()) {
					throw new Exception("未填写学号");
				}

				String name = sheet.getRow(nowJ).getCell(3).getStringCellValue();
				Integer sex = Integer.parseInt(sheet.getRow(nowJ).getCell(4).getStringCellValue());
				String grade = String.valueOf(sheet.getRow(nowJ).getCell(5).getNumericCellValue());
				String collageName = sheet.getRow(nowJ).getCell(6).getStringCellValue();
				if (collageName.isEmpty()) {
					throw new Exception("不存在学院名");
				}

				String majorName = sheet.getRow(nowJ).getCell(8).getStringCellValue();
				if (majorName.isEmpty()) {
					throw new Exception("不存在专业名");
				}

				Map major = this.majorDao.getMajorId(majorName);
				if (major == null) {
					throw new Exception("专业ID错误");
				}

				String majorID = (String)major.get("maj_id");
				String clsNum = String.valueOf(sheet.getRow(nowJ).getCell(9).getStringCellValue());
				if(clsNum.isEmpty()){
					throw new Exception("缺少班号");
				}

				String classId = this.classDao.getClaIdByMajorIdAndNum(majorID, clsNum, grade);
				if (classId == null) {
					throw new Exception("不存在班级");
				}

				list.add(new Student(IDUtil.getPrimaryKey(), studentNum, "无昵称", name, studentNum, studentNum, "未知", studentNum, "湖南科技大学", classId));
				++nowJ;
			}
		} catch (Exception var23) {
			System.out.println("fdfsdghjk=========");
			if ("class org.springframework.dao.DuplicateKeyException".equals(var23.getClass().toString())) {
				throw new Exception("数据已存在 问题可能发生在第" + nowJ + "行");
			}

			throw new Exception("文件读取失败：格式错误-" + var23.getMessage() + " 问题可能发生在第" + nowJ + "行");
		}

		File willDeleteFile = new File(filePath);
		if (!willDeleteFile.delete()) {
			throw new Exception("文件删除失败");
		} else {
			Map<String, Object> result = new TreeMap();
			result.put("msg", "成功");
			result.put("list", list);
			return result;
		}
	}



	/*
	 * @Author Tonited
	 * @Description //TODO 读取批量上传教师文件并返回教师列表及提示，如果发生错误则返回null和报错信息，初始账号和密码都是教工号
	 * @Date 14:57 2020/10/30
	 * @Param [file, collageId]
	 * @return java.util.Map<java.lang.String,java.lang.Object>
	 	msg:报错信息String，list:学生列表List<Student>
	 **/
	@Override
	@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
	public Map<String, Object> readTeacher(MultipartFile file, String collageId) throws Exception {
		String filePath = "";
		List<Teacher> list = new ArrayList<>();
		try{
			filePath = upload(file);
		} catch (Exception e) {
			throw new Exception( "文件上传失败："+e.getMessage());
		}
		Workbook wb  = null;
		FormulaEvaluator formulaEvaluator = null;
		File excelFile = new File(filePath);
		InputStream is = new FileInputStream(filePath);
		// 判断文件是xlsx还是xls
		if (excelFile.getName().endsWith("xlsx")) {
			wb = new XSSFWorkbook(is);
			formulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) wb);
		}else {
			wb = new HSSFWorkbook(is);
			formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) wb);
		}
		Sheet sheet = wb.getSheetAt(0);
		int nowJ = 1;//当前行数
		try {
			//对于每一行存储数据
			while (true) {
				Row teacherRow = sheet.getRow(nowJ);
				if(teacherRow==null) {
					break;
				}
				teacherRow.getCell(0).setCellType(CellType.STRING);
				String teacherNum =teacherRow.getCell(0).getStringCellValue();
				if(teacherNum.isEmpty()) {
					throw new Exception("未填写工号");
				}
				//教师密码
				sheet.getRow(nowJ).getCell(1).setCellType(CellType.STRING);
				String passwd = sheet.getRow(nowJ).getCell(1).getStringCellValue();
				if(passwd.isEmpty()) {
					throw new Exception("未填写密码");
				}
				//教师姓名
				sheet.getRow(nowJ).getCell(2).setCellType(CellType.STRING);
				String name = sheet.getRow(nowJ).getCell(2).getStringCellValue();
				sheet.getRow(nowJ).getCell(3).setCellType(CellType.STRING);
				String email = sheet.getRow(nowJ).getCell(3).getStringCellValue();
				if(email.isEmpty()){
					throw new Exception("未填写邮箱");
				}
				sheet.getRow(nowJ).getCell(4).setCellType(CellType.STRING);
				String phone = sheet.getRow(nowJ).getCell(4).getStringCellValue();
				if(phone.isEmpty()){
					throw new Exception("未填写电话号码");
				}
				//获取学院Id
				//学院名
//				sheet.getRow(nowJ).getCell(5).setCellType(CellType.STRING);
//				String collageName = sheet.getRow(nowJ).getCell(5).getStringCellValue();
//				if(collageName.isEmpty()){
//					throw new Exception("不存在学院名");
//				}
//				collageId = collegeDao.getCollageIdByName(collageName);//获取学院ID
				list.add(new Teacher(IDUtil.getPrimaryKey(),teacherNum,name,passwd,phone,email,collageId));
				//学院Id使用的是前端传递过来的ID
//				String collageId = collegeDao.getCollageIdByName(collageName);
				//初始账号和密码都是学号
				nowJ++;
			}
		}catch (Exception e){
			if("class org.springframework.dao.DuplicateKeyException".equals(e.getClass().toString())) {
				throw new Exception( "数据已存在 问题可能发生在第"+nowJ+"行");
			} else {
				//e.printStackTrace();
				throw new Exception("文件读取失败：格式错误-"+e.getMessage()+" 问题可能发生在第"+nowJ+"行");
			}
		}
		File willDeleteFile = new File(filePath);
		if(!willDeleteFile.delete()){
			throw new Exception("文件删除失败");
		}
		Map<String, Object> result = new TreeMap<>();
		result.put("msg","成功");
		result.put("list",list);
		return result;
	}

	/*
	 * @Author Tonited
	 * @Description //TODO 读取题目文件并返回题目列表
	 * @Date 17:42 2020/10/30
	 * @Param [file, courseId]
	 * @return java.util.Map<java.lang.String,java.lang.Object>
	 **/
	@Override
	@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
	public Map<String, Object> readQuestions(MultipartFile file, String courseId) throws Exception {
		String filePath = "";
		List<NewQuestionRecord> list = new ArrayList<>();
		try{
			filePath = upload(file);
		} catch (Exception e) {
			throw new Exception( "文件上传失败："+e.getMessage());
		}
		Document document = new Document(filePath);
		document.loadFromFile(filePath);

		//图片全部转存，并转换成html形式
		PictureIO.doPic(document);

		int nowQue = 0;
		int typeInt = 0;
		int easyChoose = 0;
		//答案列表
		List<AlternativeAnswerRecord> ansList = null;
		try {
			Section section = document.getSections().get(0);
			ParagraphCollection paragraphs = section.getParagraphs();

			//对于每一段存储数据
			for (int j =0; j < section.getParagraphs().getCount(); ) {
				nowQue++;
				//读取题目元数据
				String queMetaDataString = paragraphs.get(j++).getText().replace("[","").replace("]","");
				String[] queMetaData = queMetaDataString.split(";");
				if(queMetaData.length<=1){
					queMetaData = queMetaDataString.split("；");
				}
				//获取题目类型信息
				String type = queMetaData[0].trim();
				if(type.contains("选")){
					typeInt = 2;
				}else if(type.contains("填")){
					typeInt=3;
				}else{//简答题
					typeInt=4;
				}
				String typeId = questionTypeDao.getQeuTypIdByQueTyp(typeInt);

				//获取题目难易度信息
				String easy = queMetaData[1].trim();
				if(easy.contains("简") || easy.contains("易")){
					easyChoose = 1;
				}else if(easy.contains("中")){
					easyChoose=2;
				}else{//困难题
					easyChoose=3;
				}

				//获取课程目标信息
				String couTarNum = queMetaData[2].trim();//课程目标
				String courseTargetId = courseTargetDao.getCouTarIdByNumAndCourseId(couTarNum,courseId);
				if(courseTargetId==null){
					throw new Exception("课程目标代码不存在");
				}

				//获取章节号
				String[] capter = queMetaData[4].trim().split("\\.");
				if (capter.length < 4) {
					throw new Exception("章节格式错误");
				}
				String capId = capterDao.getCapIdByCapNum(courseId, Integer.parseInt(capter[0]), Integer.parseInt(capter[1]), Integer.parseInt(capter[2]), Integer.parseInt(capter[3]));
				if (capId == null) {
					throw new Exception("章节不存在");
				}

				//获取知识点
				String point = queMetaData[3].trim();

				//获取题目内容
				StringBuilder content = new StringBuilder();
				while(!paragraphs.get(j).getText().isEmpty() && j < section.getParagraphs().getCount()-1){
					String rowContant = "<p>" + paragraphs.get(j).getText().replace(" ","&nbsp").replace("&778604985"," ") +"</p>";
					content.append(rowContant);
					j++;
				}
				j++;//跳过空行


				//获取解析
				j++;//跳过”解析:“
				String analyse = "";
				while(!paragraphs.get(j).getText().isEmpty() && j < section.getParagraphs().getCount()-1){
					analyse += "<p>" + paragraphs.get(j).getText().replace(" ","&nbsp").replace("&778604985"," ") +"</p>";
					j++;
				}
				j++;//跳过空行
				j++;//跳过 答案：
				ansList = new ArrayList<>();
				while(!paragraphs.get(j).getText().isEmpty() && j < section.getParagraphs().getCount()-1){
					String rowContent = paragraphs.get(j).getText();

					//如果是选择题
					if(type.contains("选")) {
						if(rowContent.isEmpty()){
							j+=2;
							break;
						}
						String[] nowAns = rowContent.split(" ");
						if (nowAns.length < 2) {
							throw new Exception("答案数据异常");
						}
						if (nowAns[nowAns.length - 1].contains("是")) {
							AlternativeAnswerRecord newAnswer = new AlternativeAnswerRecord(IDUtil.getPrimaryKey(), 1, "<p>"+nowAns[0].trim().replace(" ","&nbsp").replace("&778604985"," ")+"</p>");
							ansList.add(newAnswer);
						} else {
							AlternativeAnswerRecord newAnswer = new AlternativeAnswerRecord(IDUtil.getPrimaryKey(), 2, "<p>"+nowAns[0].trim().replace(" ","&nbsp").replace("&778604985"," ")+"</p>");
							ansList.add(newAnswer);
						}
					} else{ //如果是简答题填空题
						char[] rowContentChars = rowContent.toCharArray();
						if(Character.isDigit(rowContentChars[0]) || Character.isLetter(rowContentChars[0])){
							if(rowContentChars.length>1){
								if(rowContentChars[1]=='、' || rowContentChars[1]==' '){
									rowContentChars[0] = ' ';
									rowContentChars[1] = ' ';
									rowContent = String.valueOf(rowContentChars);
								}
							}
							rowContent = rowContent.trim();
						}
						AlternativeAnswerRecord newAnswer = new AlternativeAnswerRecord(IDUtil.getPrimaryKey(), 1, "<p>"+rowContent.replace(" ","&nbsp").replace("&778604985"," ")+"</p>");
						ansList.add(newAnswer);
					}
					j++;
				}
				list.add(new NewQuestionRecord(IDUtil.getPrimaryKey(),easyChoose, content.toString(),analyse,point,courseId,capId,typeId,ansList,courseTargetId));
				j++;//跳过一个空行
				j++;//跳过两个空行
				// 初始账号和密码都是学号
			}
//			for(NewQuestionRecord questionRecord : list){
//				questionDao.insertQuestion(questionRecord.getQueId(),
//						questionRecord.getLevel(),
//						questionRecord.getContent(),
//						questionRecord.getAnalysis(),
//						questionRecord.getPoint(),
//						courseId,
//						questionRecord.getChaId(),
//						questionRecord.getQueTypId(),
//						questionRecord.getCouTarId());
//			}
		}catch (Exception e){
			//e.printStackTrace();
			if("class org.springframework.dao.DuplicateKeyException".equals(e.getClass().toString())) {
				throw new Exception( "数据已存在");
			} else {
				throw new Exception("文件读取失败：格式错误-"+e.getMessage()+" 问题可能发生在第"+nowQue+"组数据");
			}
		}
		File willDeleteFile = new File(filePath);
		if(!willDeleteFile.delete()){
			throw new Exception("文件删除失败");
		}
		Map<String, Object> result = new TreeMap<>();
		result.put("msg","成功");
		result.put("list",list);
		return result;
	}
	

}
